package com.hulman.oms.shiro;

import com.hulman.oms.bean.Result;
import com.hulman.oms.util.ServletUtil;
import com.hulman.oms.util.JsonUtil;
import com.hulman.oms.util.StringUtil;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.AuthenticationFilter;

import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;

/**
 * @Author: maxwellens
 */
public class JwtAuthenticationFilter extends AuthenticationFilter
{
    private boolean executeLogin(ServletRequest request, ServletResponse response) throws IOException
    {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        JwtToken jwtToken = new JwtToken(ServletUtil.getToken(httpServletRequest));
        Subject subject = getSubject(request, response);
        try
        {
            subject.login(jwtToken);
            return true;
        } catch (AuthenticationException e)
        {
            return doLoginFailed(request, response);
        }
    }

    private boolean doLoginFailed(ServletRequest request, ServletResponse response) throws IOException
    {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        String url = httpServletRequest.getRequestURI();
        if (url.endsWith(".html") || "/".equals(url))
        {
            String redirectUrl = getLoginUrl();
            if (!"/".equals(url))
            {
                String callback = URLEncoder.encode(ServletUtil.getUrl(httpServletRequest), "UTF-8");
                redirectUrl = redirectUrl + "?callback=" + callback;
            }
            httpServletResponse.sendRedirect(redirectUrl);
            return false;
        } else
        {
            Result result = new Result(Result.CODE_UNAUTHORIZED, "认证失败或会话过期，请重新登录", null);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(JsonUtil.toJSONString(result));
            response.flushBuffer();
        }
        return false;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception
    {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        if (isLoginRequest(request, response))
        {
            return false;
        } else
        {
            String token = ServletUtil.getToken(httpServletRequest);
            if (StringUtil.isEmpty(token))
            {
                return doLoginFailed(request, response);
            } else
            {
                //没有登录则尝试重新登录
                return executeLogin(request, response);
            }
        }
    }
}